package com.panopset.flywheel;

import java.io.IOException;
import static com.panopset.Util.*;

import java.io.File;
import java.io.StringWriter;
import java.util.Date;
import java.util.Vector;

/**
 * If a report directory has been specified in the reserved property value
 * <b>com.panopset.flywheel.reports</b>, this class will be used during script
 * execution to prepare reports that show the template structure in html format.
 *
 * @author Karl Dinwiddie
 */
public final class Report {

    /**
     * Flywheel.
     */
    private final Flywheel pflywheel;

    /**
     * Report directory.
     */
    private final File preportDirectory;

    /**
     * Source files.
     */
    private final Vector<SourceFile> sourceFiles = new Vector<SourceFile>();

    /**
     * Template line replacements.
     */
    private final Vector<String[]> templateLinkReplacements
        = new Vector<String[]>();

    /**
     * @param flywheel
     *            Flywheel to report on.
     * @param reportDirectory
     *            Where to put reports.
     */
    public Report(final Flywheel flywheel, final File reportDirectory) {
        pflywheel = flywheel;
        preportDirectory = reportDirectory;
        mkdirs(this.preportDirectory);
    }

    /**
     * Do replacements.
     *
     * @param string
     *            String to perform replacements on.
     * @return results.
     */
    private String doReplacements(final String string) {
        String s = string.replace("<", "&lt;").replace(">", "&gt;") + DOS_RTN;
        for (String[] r : templateLinkReplacements) {
            s = s.replace(r[0], r[1]);
        }
        return s;
    }

    /**
     * Execute report generation.
     * @throws IOException IO Exception.
     */
    public void exec() throws IOException {
        for (SourceFile sf : sourceFiles) {
            String[] s = new String[2];
            s[0] = pflywheel.openDirective + pflywheel.directive + "t "
                    + sf.getRelativePath() + pflywheel.closeDirective;
            s[1] = pflywheel.openDirective + pflywheel.directive
                    + "t <a href=\""
                    + ReservedWords.DEPTH_CHARGE + sf.getRelativePath()
                    + ".html\">"
                    + sf.getRelativePath() + "</a>" + pflywheel.closeDirective;
            if (!templateLinkReplacements.contains(s)) {
                templateLinkReplacements.add(s);
            }
        }
        for (SourceFile sf : sourceFiles) {
            String[] s = new String[2];
            s[0] = pflywheel.openDirective + pflywheel.directive + "l "
                    + sf.getRelativePath() + pflywheel.closeDirective;
            s[1] = pflywheel.openDirective + pflywheel.directive
                    + "l <a href=\""
                    + ReservedWords.DEPTH_CHARGE + sf.getRelativePath()
                    + ".html\">"
                    + sf.getRelativePath() + "</a>" + pflywheel.closeDirective;
            if (!templateLinkReplacements.contains(s)) {
                templateLinkReplacements.add(s);
            }
        }
        Date date = new Date();
        for (SourceFile sf : sourceFiles) {
            StringWriter sw = new StringWriter();
            for (String s : sf.getSourceLines()) {
                sw.append(doReplacements(s));
            }
            String templateFilePath = getCanonicalPath(preportDirectory)
                    + PATH_SEP + "com.panopset.templateReport.txt";
            File templateFile = new File(templateFilePath);
            if (!templateFile.exists()) {
                pflywheel.copyPackageResource(
                        "/com/panopset/flywheel/templateReport.txt",
                        templateFilePath);
            }
            int depth = sf.getDepth();
            StringWriter depthCharge = new StringWriter();
            for (int i = 0; i < depth; i++) {
                depthCharge.append("../");
            }
            Flywheel.Builder b = new Flywheel.Builder().targetDirectory(
                    preportDirectory).file(templateFile).map("fileName",
                    sf.getRelativePath() + ".html").map("currentFileName",
                    sf.getRelativePath()).map("topFile",
                    pflywheel.get(ReservedWords.FILE)).map("depthCharge",
                    depthCharge.toString()).map("last_modified",
                    com.panopset.Util.LAST_MODIFIED_FORMAT.format(date)).map(
                    "content",
                    sw.toString().replace(ReservedWords.DEPTH_CHARGE,
                            depthCharge.toString()));
            if (isPopulated(pflywheel.reportsHref)
                    && isPopulated(pflywheel.reportsHomeLinkTitle)) {
                b.map("home", "<a href=\"" + depthCharge.toString()
                        + pflywheel.reportsHref + "\">"
                        + pflywheel.reportsHomeLinkTitle + "</a>");
            }
            b.construct().exec();
        }
    }

    /**
     * Add source file.
     *
     * @param sourceFile
     *            Source file to add.
     */
    void addSourceFile(final SourceFile sourceFile) {
        for (SourceFile sf : sourceFiles) {
            if (sourceFile.equals(sf)) {
                return;
            }
        }
        sourceFiles.add(sourceFile);
    }
}
